//本包，包含了：已配对点的路径生成方法
package Model.TransFormModel;

import Model.SurroundModel.Ship;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;

public class Path {
    public Ship[][] SE;
    public int time = 0;

    public Path() {

    }

    public Path(Ship[][] SE) {
        this.SE = SE;
    }

    //计算两船之间得距离
    public double Getdistance(Ship ship1, Ship ship2) {
        double a = Math.pow(ship1.x - ship2.x, 2) + Math.pow(ship1.y - ship2.y, 2);
        return Math.sqrt(a);
    }

    //根据路径长度和时间来设置速度
    public void SetV(Ship[][] SE, double time) {
        for (int i = 1; i <= SE.length - 1; i++) {
            double dis = Getdistance(SE[i][0], SE[i][1]);
            SE[i][0].setV(dis / time);
        }
    }

    //计算路径与x轴得夹角
    public void Getθ(Ship[][] SE) {
        double a;
        for (int i = 1; i <= SE.length - 1; i++) {
            a = Math.atan(Math.abs(SE[i][0].y - SE[i][1].y) / Math.abs(SE[i][0].x - SE[i][1].x));
            SE[i][0].θ = a;
        }
    }

    //计算下一次ship移动得位置并存入ship的history数组
    public void Calcposition(Ship[][] SE) {
        time++;
        for (int i = 1; i <= SE.length - 1; i++) {
            if (Math.abs(SE[i][0].x - SE[i][1].x) < 1 && Math.abs(SE[i][0].y - SE[i][1].y) < 1) {
                SE[i][0].isFinish = true;
            }
        }
        //预处理所有船的下一次位置
        for (int i = 1;i<= SE.length-1;i++){
            if (SE[i][0].isFinish ==false) {
                if (SE[i][1].x - SE[i][0].x == 0){ SE[i][0].x1 = SE[i][1].x;}
                else {
                    SE[i][0].x1 = SE[i][0].x + (SE[i][1].x - SE[i][0].x) / Math.abs(SE[i][1].x - SE[i][0].x) * SE[i][0].v * Math.cos(SE[i][0].θ);
                }
                if (SE[i][1].y - SE[i][0].y == 0) {SE[i][0].y1 = SE[i][1].y;}
                else {
                    SE[i][0].y1 = SE[i][0].y + (SE[i][1].y - SE[i][0].y) / Math.abs(SE[i][1].y - SE[i][0].y) * SE[i][0].v * Math.sin(SE[i][0].θ);
                }
            }
        }
        //对预处理的位置进行碰撞检测 如果会有碰撞则保持原来的位置，如果没有发生碰撞就用新的位置取代原来的位置
        for (int i = 1; i <= SE.length - 1; i++) {
            //如果没有发生碰撞就将移动的位置赋给船
            if (!MisCollision(SE[i][0], SE) && SE[i][0].isFinish == false) {
                SE[i][0].x = SE[i][0].x1;
                SE[i][0].y = SE[i][0].y1;
                SE[i][0].storeXY();
            } else {
                //如果发生碰撞，点就保持不动
                SE[i][0].x1 = SE[i][0].x;
                SE[i][0].y1 = SE[i][0].y;
                SE[i][0].storeXY();
            }
        }
    }

    //碰撞检测
    public boolean isCollision(Ship ship, double dis, Ship[][] SE) {
        ship.isScan = true;
        for (int i = 1; i <= SE.length - 1; i++) {
            if (SE[i][0].isScan == true || SE[i][0].isFinish == true) {
                continue;
            } else {
                double a = Math.sqrt(Math.pow(ship.x1 - SE[i][0].x1, 2) + Math.pow(ship.y1 - SE[i][0].y1, 2));
                if (a < dis) {
                    System.out.println(111);
                    return true;
                }
            }
        }
        return false;
    }

    //修改的碰撞检测，思想是将一条船的前后两个点连线去与其他的船的连线判断是否会交叉
    public boolean MisCollision(Ship ship, Ship[][] SE) {
        if (!ship.Index.isEmpty()) {
            for (int a : ship.Index) {
                double num1, num2, num3, num4;
                num1 = compute(ship.x - ship.x1, ship.y - ship.y1, ship.x - SE[a][0].x, ship.y - SE[a][0].y);
                num2 = compute(ship.x - ship.x1, ship.y - ship.y1, ship.x - SE[a][0].x1, ship.y - SE[a][0].y1);
                num3 = compute(ship.x - SE[a][0].x, ship.y - SE[a][0].y, SE[a][0].x - SE[a][0].x1, SE[a][0].y - SE[a][0].y1);
                num4 = compute(ship.x1 - SE[a][0].x, ship.y1 - SE[a][0].y, SE[a][0].x - SE[a][0].x1, SE[a][0].y - SE[a][0].y1);
                if ((num1 * num2 < 0 && num3 * num4 <= 0) || (num1 * num2 <= 0 && num3 * num4 < 0)) {
                    System.out.println(ship.num + "与" + SE[a][0].num + "碰撞了");
                    return true;
                }
            }
        }
        return false;
    }

    //结束检测
    public boolean Finish(Ship[][] SE) {
        for (int i = 1; i <= SE.length - 1; i++) {
            if (SE[i][0].isFinish == false)
                return false;
        }
        return true;
    }

    //判断路径交叉的船并将对应的索引存到属性里
    public void CollisionShip(Ship[][] SE) {
        for (int i = 1; i <= SE.length - 1; i++) {
            for (int j = i + 1; j <= SE.length - 1; j++) {
                double num1, num2, num3, num4;
                num1 = compute(SE[i][0].x - SE[i][1].x, SE[i][0].y - SE[i][1].y, SE[i][0].x - SE[j][0].x, SE[i][0].y - SE[j][0].y);
                num2 = compute(SE[i][0].x - SE[i][1].x, SE[i][0].y - SE[i][1].y, SE[i][0].x - SE[j][1].x, SE[i][0].y - SE[j][1].y);
                num3 = compute(SE[i][0].x - SE[j][0].x, SE[i][0].y - SE[j][0].y, SE[j][0].x - SE[j][1].x, SE[j][0].y - SE[j][1].y);
                num4 = compute(SE[i][1].x - SE[j][0].x, SE[i][1].y - SE[i][0].y, SE[j][0].x - SE[j][1].x, SE[j][0].y - SE[j][1].y);
                if ((num1 * num2 < 0 && num3 * num4 <= 0) || (num1 * num2 <= 0 && num3 * num4 < 0)) {
                    SE[i][0].storeIndex(j);
                }
            }
        }
    }

    //计算叉积
    public double compute(double x1, double y1, double x2, double y2) {
        return x1 * y2 - y1 * x2;
    }

    //计算船只的距离并把它保存在船的dis属性里
    public void Storedistance(Ship[][] SE, double dis) {
        for (int i = 1; i <= SE.length - 1; i++) {
            double sumdis = 0;
            double num = 0;
            double Mindis = dis;

            LinkedHashMap<String, Double> shipdis = new LinkedHashMap<>();
            for (int j = 1; j <= SE.length - 1; j++) {
                double a = Getdistance(SE[i][0], SE[j][0]);
                if (a < dis && a != 0) {
                    shipdis.put("编号" + SE[j][0].num, a);
                    sumdis = sumdis + a;
                    num++;
                    if (a < Mindis) {
                        Mindis = a;
                    }
                }
            }
            shipdis.put("最短距离", Mindis);
            if (num != 0)
                shipdis.put("平均距离", sumdis / num);
            SE[i][0].dis.put(this.time, shipdis);

//            List<Double> shipMinDis = new ArrayList<>();
//            List<Double> shipEvDis = new ArrayList<>();
//            shipMinDis.add(Mindis);
//            shipEvDis.add(sumdis / num);

            System.out.println("每帧的平均距离" + i + ":" +sumdis/num);

        }
    }

    //计算一项表格绘图所用数据
//    public ArrayList<ChartData> tableData = new ArrayList<ChartData>(); //存储所有船的历史平均值和时间

    public void CalculateTabularData(Ship[][] SE) {
        //计算每一次刷新后的船的平均距离
//        ChartData t = new ChartData();
//        t.time = this.time; //存储数据对应时间
//        for (int i = 1; i <= SE.length - 1; i++) {
//            t.Mindis += SE[i][0].dis.get(t.time).get("最短距离");
//            if (SE[i][0].dis.get(t.time).get("平均距离") != null)
//                t.Meandis += SE[i][0].dis.get(t.time).get("平均距离");
//            //System.out.println("平均距离:"+ i + ":" +SE[i][0].dis.get(t.time).get("平均距离"));
//        }
//        t.Mindis = t.Mindis / (SE.length - 1);  //所有船的平均最短距离
//        t.Meandis = t.Meandis / (SE.length - 1);     //所有船的平均平均距离
//        System.out.println("存储每帧的会表格数据" + t);
//        tableData.add(t);   //存储
    }

}


